home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 2 / Atari Mega Archive CD - Volume 2.iso / minix / up1510b.tgz / up1510b / src / commands / atari / cv.c < prev    next >
C/C++ Source or Header  |  1990-07-23  |  10KB  |  431 lines

  1. /*
  2.  * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
  3.  * See the copyright notice in the file "../Copyright".
  4.  */
  5. /*
  6.  * Convert ACK a.out file to ST-Minix object format.
  7.  */
  8.  
  9. #ifdef UNIX
  10. #include <stdio.h>
  11. #include "../../include/a.out.h"
  12. #undef    S_ABS    /* avoid collision */
  13. #include "out.h"
  14. #else
  15. #include <sys/types.h>
  16. #include <stdlib.h>
  17. #include <stdio.h>
  18. #include <a.out.h>
  19. #undef    S_ABS    /* avoid collision */
  20. #include <out.h>
  21. #endif
  22.  
  23. #define TXTSEG    0
  24. #define ROMSEG    1
  25. #define DATSEG    2
  26. #define BSSSEG    3
  27. #define ENDSEG    4
  28.  
  29. struct outhead    outhead;
  30. struct outsect    outsect[ENDSEG+1];
  31.  
  32. int    Rflag;
  33.  
  34. char    *output_file;
  35. char    *program;
  36. char    *chmemstr;
  37.  
  38. main(argc, argv)
  39.     int    argc;
  40.     char    *argv[];
  41. {
  42.     register int    i;
  43.  
  44.     program = argv[0];
  45.     while (argc > 1) {
  46.         switch (argv[1][0]) { 
  47.         case '-':
  48.             if (strcmp(argv[1], "-R") == 0) {
  49.                 Rflag++;
  50.                 argc--;
  51.                 argv++;
  52.                 continue;
  53.             }
  54.             /* fall through */
  55.         case '+':
  56.         case '=':
  57.             chmemstr = argv[1];
  58.             argc--;
  59.             argv++;
  60.             continue;
  61.         }
  62.         break;
  63.     }
  64.     if (argc != 3)
  65.         fatal("Usage: %s [-R] [+-= amount] <ACK object> <MINIX-ST object>", argv[0]);
  66.  
  67.     if ((freopen(argv[1], "r", stdin)) == NULL)
  68.         fatal("Can't read %s", argv[1]);
  69.     if ((freopen(argv[2], "w", stdout)) == NULL)
  70.         fatal("Can't write %s", argv[2]);
  71.     output_file = argv[2];
  72.  
  73.     getofmt((char *)&outhead, SF_HEAD, stdin);
  74.     if (BADMAGIC(outhead))
  75.         fatal("Not an ack object file");
  76.     if (outhead.oh_flags & HF_LINK)
  77.         fatal("Contains unresolved references");
  78.     if (outhead.oh_nsect < BSSSEG+1)
  79.         fatal("Input must have at least %d sections, not %ld",
  80.             BSSSEG+1, outhead.oh_nsect);
  81.     if (outhead.oh_nsect > ENDSEG+1)
  82.         fatal("Input must have at most %d sections, not %ld",
  83.             ENDSEG+1, outhead.oh_nsect);
  84.     for (i = 0; i < outhead.oh_nsect; i++)
  85.         getofmt((char *)&outsect[i], SF_SECT, stdin);
  86.  
  87.     /* A few checks */
  88.     if (outsect[BSSSEG].os_flen != 0)
  89.         fatal("bss contains initialized data");
  90.     if (! follows(ROMSEG, TXTSEG))
  91.         fatal("rom must follow text");
  92.     if (! follows(DATSEG, ROMSEG))
  93.         fatal("data must follow rom");
  94.     if (! follows(BSSSEG, DATSEG))
  95.         fatal("bss must follow data");
  96.     outsect[TXTSEG].os_size = outsect[ROMSEG].os_base - outsect[TXTSEG].os_base;
  97.     outsect[ROMSEG].os_size = outsect[DATSEG].os_base - outsect[ROMSEG].os_base;
  98.     outsect[DATSEG].os_size = outsect[BSSSEG].os_base - outsect[DATSEG].os_base;
  99.     if (outhead.oh_nsect == ENDSEG+1) {
  100.         if (! follows(ENDSEG, BSSSEG))
  101.             fatal("end segment must follow bss");
  102.         if (outsect[ENDSEG].os_size != 0)
  103.             fatal("end segment must be empty");
  104.     }
  105.     emit_head();
  106.     emit_sect(TXTSEG);
  107.     emit_sect(ROMSEG);
  108.     emit_sect(DATSEG);
  109.     emit_syms();
  110.     emit_relo();
  111. #ifndef UNIX
  112.     if (output_file) chmod(output_file, 0777 & ~umask(0));
  113. #endif
  114.     exit(0);
  115. }
  116.  
  117. emit_head()
  118. {
  119.     register    i;
  120.     long        mh[8];
  121.     long        stack;
  122.     long        chmem();
  123.  
  124.     mh[0] = 0x04100301L;
  125.     mh[1] = 0x00000020L;
  126.     mh[2] = outsect[TXTSEG].os_size + outsect[ROMSEG].os_size;
  127.     mh[3] = outsect[DATSEG].os_size;
  128.     mh[4] = outsect[BSSSEG].os_size;
  129.     mh[5] = 0;
  130.     stack = 0x00010000L - (mh[3] + mh[4]);
  131.     if ((mh[0] & 0x00200000L) == 0)        /* not SEPARATE */
  132.         stack -= mh[2];
  133.     while (stack < 0)
  134.         stack += 0x00010000L;
  135.     if (chmemstr)
  136.         stack = chmem(chmemstr, stack);
  137.     fprintf(stderr, "%ld bytes assigned to stack+malloc area\n", stack);
  138.     mh[6] = stack + (mh[3] + mh[4]);
  139.     if ((mh[0] & 0x00200000L) == 0)        /* not SEPARATE */
  140.         mh[6] += mh[2];
  141.     mh[7] = outhead.oh_nname * (long) sizeof(struct nlist);
  142.     for (i = 0; i < 8; i++)
  143.         putlong(mh[i], stdout);
  144. }
  145.  
  146. follows(segb, sega)
  147. {
  148.     register struct outsect *pb = &outsect[segb];
  149.     register struct outsect *pa = &outsect[sega];
  150.     register long        b;
  151.  
  152.     /* return 1 if segb follows sega */
  153.  
  154.     b = pa->os_base + pa->os_size;
  155.     if (pb->os_lign) {
  156.         b += pb->os_lign - 1;
  157.         b -= b % pb->os_lign;
  158.     }
  159.     return(pb->os_base == b);
  160. }
  161.  
  162. /*
  163.  * Transfer the emitted byted from one file to another.
  164.  */
  165. emit_sect(seg)
  166. {
  167.     register struct outsect *sp = &outsect[seg];
  168.     register long        sz = sp->os_flen;
  169.     register int        c;
  170.  
  171.     fseek(stdin, sp->os_foff, 0);
  172.     for (sz = sp->os_flen; sz > 0; sz--) {
  173.         c = getc(stdin);
  174.         if (c == EOF)
  175.             rderr();
  176.         c = putc(c, stdout);
  177.         if (c == EOF)
  178.             wrerr();
  179.     }
  180.     for (sz = sp->os_size - sp->os_flen; sz > 0; sz--) {
  181.         c = putc(0, stdout);
  182.         if (c == EOF)
  183.             wrerr();
  184.     }
  185. }
  186.  
  187. emit_syms()
  188. {
  189.     register unsigned short nrsyms;
  190.     struct outname nbuf;
  191.     struct nlist alist;
  192.     unsigned readcount = outhead.oh_nchar;
  193.     long fi_to_co;
  194.     char *cbufp;
  195.     register int sclass;
  196.     static char segment[] = { N_TEXT, N_TEXT, N_DATA, N_BSS, N_BSS };
  197.  
  198.     if (readcount != outhead.oh_nchar || (cbufp = (char *)malloc(readcount)) == NULL) {
  199.         fprintf(stderr, "cv: out of memory\n");
  200.         exit(-1);
  201.     }
  202.  
  203.     fseek(stdin, OFF_CHAR(outhead), 0);
  204.     fread(cbufp, 1, readcount, stdin);
  205.     fi_to_co = (long)cbufp - OFF_CHAR(outhead);
  206.     fseek(stdin, OFF_NAME(outhead), 0);
  207.     alist.n_numaux = 0;
  208.     alist.n_type = 0;
  209.     for (nrsyms = outhead.oh_nname; nrsyms > 0; nrsyms--)
  210.     {
  211.         getofmt((char *)&nbuf, SF_NAME, stdin);
  212.         if (nbuf.on_foff == 0) /* no name */
  213.             strcpy(alist.n_name, "");
  214.         else
  215.             strncpy(alist.n_name, (char *)(nbuf.on_foff + fi_to_co), 8); 
  216.         alist.n_value = nbuf.on_valu;
  217.         sclass = nbuf.on_type & S_TYP;
  218.         alist.n_sclass = (sclass == S_ABS) ? N_ABS :
  219.                         segment[sclass - S_MIN];
  220.         if (nbuf.on_type & S_EXT) {
  221.             alist.n_sclass |= C_EXT;
  222.         }
  223.         fwrite(&alist, sizeof(struct nlist), 1, stdout);
  224.     }
  225. }
  226.  
  227. emit_relo()
  228. {
  229.     register char    *ptr;
  230.     register int    len;
  231.     register int    bit;
  232.     register int    byt;
  233.     register long    last;
  234.     register long    curr;
  235.     register long    base;
  236.     register long    stop;
  237.     register long    i;
  238.     struct outrelo    outrelo;
  239.  
  240.     if (Rflag) {
  241.         putlong(0L, stdout);
  242.         return;
  243.     }
  244.     fseek(stdin, OFF_RELO(outhead), 0);
  245.     base = outsect[TXTSEG].os_base;
  246.     stop = outsect[BSSSEG].os_base;
  247.     len = (int)(((stop - base) + 15) / 16);
  248.     if (len != (((stop - base) + 15) / 16))
  249.         fatal("relo: span too big");
  250.     ptr = calloc(len, 1);
  251.     if (ptr == NULL)
  252.         fatal("out of memory");
  253.     for (i = outhead.oh_nrelo; i > 0; i--) {
  254.         getofmt((char *)&outrelo, SF_RELO, stdin);
  255.         if (outrelo.or_type & RELPC)
  256.             continue;
  257.         if (outrelo.or_nami == outhead.oh_nname)
  258.             continue;
  259.         if ((outrelo.or_type & (RELBR|RELWR)) != (RELBR|RELWR))
  260.             fatal("relo: not for 680X0");
  261.         if ((outrelo.or_type & RELSZ) != RELO4) {
  262.             static int warned;
  263.             if (!warned) {
  264.                 fprintf(stderr, "only longs can be relocated\n");
  265.                 warned++;
  266.             }
  267.         }
  268.         outrelo.or_sect -= S_MIN;
  269.         if (outrelo.or_sect < TXTSEG || outrelo.or_sect > DATSEG)
  270.             fatal("relo: bad section");
  271.         curr = outrelo.or_addr;
  272.         curr += outsect[outrelo.or_sect].os_base;
  273.         if (curr < base || curr >= stop)
  274.             fatal("relo: bad address");
  275.         curr -= base;
  276.         if (curr & 1)
  277.             fatal("relo: odd address");
  278.         curr >>= 1;
  279.         byt = (int)(curr >> 3);
  280.         bit = 1 << ((int)curr & 7);
  281.         if (ptr[byt] & bit)
  282.             fatal("relo: twice on same address");
  283.         ptr[byt] |= bit;
  284.     }
  285.     /*
  286.          * read relocation, modify to GEMDOS format, and write.
  287.          * Only longs can be relocated.
  288.          *
  289.          * The GEMDOS format starts with a long L: the offset to the
  290.          * beginning of text for the first long to be relocated.
  291.          * If L==0 then no relocations have to be made.
  292.          *
  293.          * The long is followed by zero or more bytes. Each byte B is
  294.          * processed separately, in one of the following ways:
  295.          *
  296.          * B==0:
  297.          *      end of relocation
  298.          * B==1:
  299.          *      no relocation, but add 254 to the current offset
  300.          * B==0bWWWWWWW0:
  301.          *      B is added to the current offset and the long addressed
  302.          *      is relocated. Note that 00000010 means 1 word distance.
  303.          * B==0bXXXXXXX1:
  304.          *      illegal
  305.          */
  306.     last = 0;
  307.     for (byt = 0; byt < len; byt++) {
  308.         if (ptr[byt] == 0)
  309.             continue;
  310.         for (bit = 0; bit < 8; bit++) {
  311.             if ((ptr[byt] & (1<<bit)) == 0)
  312.                 continue;
  313.             curr = ((long)byt << 3) + bit;
  314.             curr <<= 1;
  315.             curr += base;
  316.             if (last == 0)
  317.                 putlong(curr, stdout);
  318.             else {
  319.                 while (curr - last > 255) {
  320.                     if (putc(1, stdout) == EOF)
  321.                         wrerr();
  322.                     last += 254;
  323.                 }
  324.                 if (putc((int)(curr - last), stdout) == EOF)
  325.                     wrerr();
  326.             }
  327.             last = curr;
  328.         }
  329.     }
  330.     if (last == 0)
  331.         putlong(last, stdout);
  332.     else {
  333.         if (putc(0, stdout) =